import { area, pokerSTatus, suitType } from "../common/enumConfig"
import EventManager from "../common/eventManager"
import gameEvent from "../common/gameEvent"
import UIPoker from "../common/UIPoker"

 export class Poker{
    public point:number = -1
    public suit:suitType = suitType.HEITAO

    public playAreaIndex:number = -1

    private _status:pokerSTatus = pokerSTatus.CLOSE

    public get status():pokerSTatus{return this._status}
    public set status(status:pokerSTatus){this._status = status}

    private _view:UIPoker = undefined

    public get view(){return this._view}
    public set view(UIPoker:UIPoker){this._view = UIPoker}

    constructor(point:number,suit:suitType,status:pokerSTatus){
        this.point = point
        this.suit = suit
        this.status = status
    }

    public bindView(UIPoker:UIPoker){
        this.view = UIPoker
    }

    public unBindView(){
        this.view = undefined
    }
}

   export class PokerGroup{
        public _poker:Poker[] = []
        public index:number = -1
        public get poker(){return this._poker}

        public addPoker(poker:Poker){
            this._poker.push(poker)
        }
        public removePoker(){
            this._poker.pop()
        }

        public pokerEmpty(){
            return this._poker.length == 0
        }

        public top():Poker{
            return this._poker[this._poker.length - 1]
        }

    }

    // 收牌区
   export class ReceivePokerGroup extends PokerGroup{
        public suit:suitType = suitType.HEITAO

        public isSameSuit(poker:Poker){
            return poker.suit === this.suit
        }

        public isNextPoker(poker:Poker){
            if(this.pokerEmpty){
                return poker.point === 0
            }
            else{
                return poker.point === this.top().point + 1
            }
        }
    }

    // 玩牌区
    export class PlayePokerGroup extends PokerGroup{
    }

export default class gameModel{
    // 原始扑克
    private _pokers:Poker[] = []
    // 发牌区盖着的扑克
    private _closeAreaPokers:Poker[] = []
    //发牌区开着的扑克
    private _openAreaPokers:Poker[] = []
    //收牌区
    private _receiveAreaPokerGroups:ReceivePokerGroup[] = []
    //玩牌区
    private _playAreaPokerGroups:PlayePokerGroup[] = []

    private em:EventManager = EventManager.instance()

    
    public get pokers(): Poker[] {return this._pokers}
    public get closeAreaPokers(): Poker[] { return this._closeAreaPokers}
    public get openAreaPokers(): Poker[] { return this._openAreaPokers}
    public get receiveAreaPokerGroups(): ReceivePokerGroup[] { return this._receiveAreaPokerGroups}
    public get playAreaPokerGroups(): PlayePokerGroup[] { return this._playAreaPokerGroups}
    
    public static readonly CONST_RECEIVE_GROUPS:number = 4
    public static readonly CONST_PLAY_GROUPS:number = 7

    // 初始化
    public init(){
         // 初始化牌局结构
        for(let i = 0;i<gameModel.CONST_RECEIVE_GROUPS;i++){
            let receivePokerGroup = new ReceivePokerGroup()
            receivePokerGroup.index = i
            receivePokerGroup.suit = i
            this._receiveAreaPokerGroups.push(receivePokerGroup)
        }
        for(let i = 0;i<gameModel.CONST_PLAY_GROUPS;i++){
            let playePokerGroup = new PlayePokerGroup()
            playePokerGroup.index = i
            this._playAreaPokerGroups.push(playePokerGroup)
        }

        for(let point=0;point<13;point++){
            for(let suit = 0;suit<4;suit++){
                let poker = new Poker(point,suit,pokerSTatus.CLOSE)
                this._pokers.push(poker)
            }
        }
         // 洗牌
         this.shuffle(this.pokers,300)
        // 派发初始化牌局事件
        this.em.emit(gameEvent.INIT_POKER,this._pokers)
    }

    // 游戏开始
    public play(){
        // 交换牌信息
        let tmp = this._closeAreaPokers
        this._closeAreaPokers = this.pokers
        this._pokers = tmp

        // 通知UI层，发生变化
        this.em.emit(gameEvent.PLAY)

        // 发牌
        for(let cards = gameModel.CONST_PLAY_GROUPS;cards >=1;--cards){
            for(let i=0;i<cards;++i){
                let cardGroupIndex = gameModel.CONST_PLAY_GROUPS - cards + i
                let cardGroup:PokerGroup = this._playAreaPokerGroups[cardGroupIndex]
                let poker = this._closeAreaPokers[this.closeAreaPokers.length - 1]
                this._closeAreaPokers.pop()
                poker.status = i== 0 ? pokerSTatus.OPEN : pokerSTatus.CLOSE
                poker.playAreaIndex = cardGroupIndex
                cardGroup.addPoker(poker)
                this.em.emit(gameEvent.INIT_GROUP,cardGroupIndex,gameModel.CONST_PLAY_GROUPS - cards,poker,(gameModel.CONST_PLAY_GROUPS - cards)*7+i)
            }
        }
    }

    // 洗牌
    private shuffle(pokers:Poker[],count:number = 100){
        for(let i = 0; i < count; ++i){
            let card1 = Math.floor(Math.random()*pokers.length)
            let card2 = Math.floor(Math.random()*pokers.length)
            let card = this.pokers[card1]
            this.pokers[card1] = this.pokers[card2]
            this.pokers[card2] = card
        }
    }

    // 重新开始
    public restart(){
        this._pokers = []
        this._closeAreaPokers = []
        this._openAreaPokers = []
        this._receiveAreaPokerGroups = []
        this._playAreaPokerGroups = []
    }

     /*******************************************************************
     * model Event handle
     ******************************************************************/
    // 扑克牌移动到收牌区
    public pokerMovePlayAreaToReceiveArea(poker:Poker){
        for(let i = 0;i<this.receiveAreaPokerGroups.length;i++){
            if(this.receiveAreaPokerGroups[i].isSameSuit(poker)){
                let group = this.receiveAreaPokerGroups[i]
            if(group.isNextPoker(poker)){
                let playGroup = this.playAreaPokerGroups[poker.playAreaIndex]
                   playGroup.removePoker()
                   let playTopPoker = playGroup.top()
                   playTopPoker.status = pokerSTatus.OPEN
                   group.addPoker(poker)
                   this.em.emit(gameEvent.POST_UI_MOVE_RECEICEAREA_FROM_PLAYAREA,poker,i)
                   this.em.emit(gameEvent.POST_POKER_RESTATUS,playTopPoker)
                }
            }
        }
       
    }

     /*******************************************************************
     * view handle by poker click
     ******************************************************************/
    // 判断扑克所在的区域
   public isLocationArea(poker:Poker,PokerArea:area):boolean{
       switch(PokerArea){
           case area.PLATY_AREA:
               return this.playAreaPokerGroups.some((playGroup)=>{
             return playGroup.poker.some((item)=>{
               return poker.point === item.point && poker.suit === item.suit
            })
        })
        case area.CLOSE_AREA:
            return this.closeAreaPokers.some((item)=>{return item.point === poker.point && item.suit === poker.suit})
       }
       
   }

//    是否在玩牌区最外边的牌
   public isPlayAreaIndexTop(poker:Poker):boolean{
        return this.playAreaPokerGroups.some((playGroup)=>{
            let item = playGroup.poker[playGroup.poker.length -1]
            return poker.point === item.point && poker.suit === item.suit
        })
   }

   //是否在收牌区最上边的牌
   public isCloseAreaIndexTop(poker:Poker):boolean{
       let top = this.closeAreaPokers[this.closeAreaPokers.length - 1]
       return top.point == poker.point && top.suit == poker.suit
   }


   
}